<?php

namespace App\Http\Controllers;

use App\Constant\Enum;
use App\Constant\OrderEnum;
use App\Libraries\Payment\WechatPay\WechatPayPayment;
use App\Models\GroupApply;
use App\Models\Order;
use App\Models\Transaction;
use App\Models\User;
use App\Models\UserWithdraw;
use App\Services\Commission\CommissionService;
use App\Services\Group\GroupService;
use App\Services\Withdraw\UserWithdrawService;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;


class PaymentWechatController extends Controller
{
    public function paidCallback(Request $request)
    {

        Log::channel('payment')->info(json_encode([
            'method' => $request->method(),
            'uri' => $request->path(),
            'ip' => $request->ip(),
            'body' => $request->all(),
            'headers' => $request->headers->all(),
        ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));

        $inWechatpaySignature = $request->header('wechatpay-signature');// 请根据实际情况获取
        $inWechatpayTimestamp = $request->header('wechatpay-timestamp');// 请根据实际情况获取
        $inWechatpaySerial = $request->header('wechatpay-serial');// 请根据实际情况获取
        $inWechatpayNonce = $request->header('wechatpay-nonce');// 请根据实际情况获取
        // $inBody = json_encode($request->post(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);// 请根据实际情况获取，例如: file_get_contents('php://input');
        $inBody = file_get_contents('php://input');

        //dd(compact('inWechatpaySignature', 'inWechatpayTimestamp', 'inWechatpayNonce', 'inWechatpaySerial', 'inBody'));
        $config = config('wechat.payment.default');

        $apiv3Key = $config['key'];// 在商户平台上设置的APIv3密钥
        // 获取项目根目录（适用于各种服务器）
        $basePath = realpath(__DIR__ . '/../../../'); // 获取当前代码所在目录的上一级
        // 根据通知的平台证书序列号，查询本地平台证书文件，
        $platformPublicKeyInstance = Rsa::from('file://' . realpath($basePath . '/' . $config['platform_cet_path']), Rsa::KEY_TYPE_PUBLIC);

        // 检查通知时间偏移量，允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
        $verifiedStatus = Rsa::verify(
        // 构造验签名串
            Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
            $inWechatpaySignature,
            $platformPublicKeyInstance
        );
        Log::channel('payment')->debug(json_encode(compact('timeOffsetStatus', 'verifiedStatus'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));

        DB::beginTransaction();
        try {
            // 转换通知的JSON文本消息为PHP Array数组
            $contents = (array)json_decode($inBody, true);
            ['resource' => [
                'ciphertext' => $ciphertext,
                'nonce' => $nonce,
                'associated_data' => $aad
            ]] = $contents;
            $decryptResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
            $payload = (array)json_decode($decryptResource, true);
            Log::channel('payment')->debug(json_encode([
                'payload' => $payload,
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));

            $outTradeNo = $payload['out_trade_no'] ?? null;
            $tradeState = $payload['trade_state'] ?? null;
            $tradeStateDesc = $payload['trade_state_desc'] ?? null;

            if (!$outTradeNo || !$tradeState || !$tradeStateDesc) {
                throw new \Exception("报文格式错误");
            }
            /** @var Order $order */
            $order = Order::query()->with('user')->where('order_no', $outTradeNo)->first();
            if (!$order) {
                throw new \Exception('订单不存在');
            }
            if ($order->status != OrderEnum::STATUS_PENDING) {
                throw new \Exception('订单已处理');
            }
            /** @var User $user */
            $user = $order->user;

            if ($tradeState == 'SUCCESS') {
                $order->update([
                    'status' => OrderEnum::STATUS_PAID,
                    'out_trade_no' => $payload['transaction_id'] ?? '-',
                    'paid_at' => Carbon::now(),
                    'trader_message' => sprintf("%s:%s", $tradeState, $tradeStateDesc),
                ]);
                GroupApply::where('uid',$user->id)->where("status","pending")->update(['status'=>"approved",'is_pay'=>1]);
                GroupService::make($user);
                if ($order->type == OrderEnum::TYPE_ADVANCED_GROUP) {
                    $user->update([
                        'is_advanced_group' => 1
                    ]);
                }
                CommissionService::distributeSubMemberGroup($user);
            } else {
                $order->update([
                    'status' => OrderEnum::STATUS_CLOSED,
                    'trader_message' => sprintf("%s:%s", $tradeState, $tradeStateDesc),
                ]);
            }
            DB::commit();
        } catch (\Exception $e) {
            //dd($e->getMessage());
            DB::rollBack();
            Log::channel('payment')->error($e);
            return response()->json([
                'code' => 'FAIL',
                'message' => '处理失败',
            ]);
        }
    }

    public function transferCallback(Request $request)
    {
        Log::channel('transfer')->info(json_encode([
            'method' => $request->method(),
            'uri' => $request->path(),
            'ip' => $request->ip(),
            'body' => $request->all(),
            'headers' => $request->headers->all(),
        ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));

        $config = config('wechat.payment.default');
        $apiv3Key = $config['key'];

        DB::beginTransaction();
        try {
            $contents = $request->post();
            ['resource' => [
                'ciphertext' => $ciphertext,
                'nonce' => $nonce,
                'associated_data' => $aad
            ]] = $contents;
            $decryptResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
            $payload = (array)json_decode($decryptResource, true);
            Log::channel('payment')->debug(json_encode([
                'callback' => $payload,
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));


            $outBatchNo = $payload['out_bill_no'] ?? null;
            $batchId = $payload['transfer_bill_no'] ?? null;
            if (!$outBatchNo || !$batchId) {
                throw new \Exception("参数异常");
            }

            $transaction = Transaction::query()->where([
                'transaction_no' => $outBatchNo,
                'remote_order_no' => $batchId,
                'status' => Enum::TRANSACTION_STATUS_PENDING,
            ])->first();

            if (!$transaction) {
                throw new \Exception('交易信息不正确');
            }
            /** @var UserWithdraw $userWithdraw */
            $userWithdraw = UserWithdraw::query()->findOrFail($transaction->getAttribute('user_withdraw_id'));
            if ($userWithdraw->getAttribute('status') != Enum::WITHDRAW_STATUS_APPROVED) {
                throw new \Exception('数据异常，转账未审核!');
            }

            $batchDetailId = $transaction->batch_detail_no;
            $result = WechatPayPayment::makeInquiry([
                'out_batch_no' => $outBatchNo,
                'out_batch_detail_no' => $batchDetailId,
            ]);

            $status = strtolower($result['state'] ?? 'unknown');

            if ($status != 'success') {
                $transaction->update([
                    'status' => Enum::TRANSACTION_STATUS_REJECT,
                    'finished_at' => Carbon::now(),
                ]);
                $userWithdraw->update([
                    'remark' => $userWithdraw->getAttribute('remark') . ' ###转账失败：' . $status,
                ]);
                UserWithdrawService::handleWalletWhenTransactionFailed($userWithdraw);
            } else {
                $transaction->update([
                    'status' => Enum::TRANSACTION_STATUS_APPROVED,
                    'finished_at' => Carbon::now(),
                ]);
                UserWithdrawService::handleWalletWhenTransactionSuccess($userWithdraw);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::channel('payment')->error($e);
            return response()->json([
                'code' => 'FAIL',
                'message' => '处理失败',
            ]);
        }
    }
}
